﻿// Copyright 2010 Maxime Serrano <lastchronicler@gmail.com>
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ForgeCraft
{

    #region Constructs

    public struct BlockInfo
    {
        public Block type;
        public byte info;
        public BlockInfo(Block type, byte info)
        {
            this.type = type;
            this.info = info;
        }
        public BlockInfo(byte type, byte info)
        {
            this.type = (Block)type;
            this.info = info;
        }
    }

    public struct ItemInfo
    {
        public Item type;
        public short info;
        public ItemInfo(Item type, short info)
        {
            this.type = type;
            this.info = info;
        }
        public ItemInfo(short type, short info)
        {
            this.type = (Item)type;
            this.info = info;
        }
    }

    #endregion

    #region Items

    public struct Items
    {
        public static List<Blocks> ItemList = new List<Blocks>();

        public static List<ItemPerms> ItemPermissions = new List<ItemPerms>();
        public class ItemPerms
        {
            public short type;
            public Permission baseRank;
            public List<Permission> disallow = new List<Permission>();
            public List<Permission> allow = new List<Permission>();
        }

        public static readonly Item[] ToolIsDurable = new Item[] {
            //Tool Durability
            Item.Cake,
            Item.ChainmailBoots,
            Item.ChainmailChestplate,
            Item.ChainmailHelmet,
            Item.ChainmailPants,
            Item.DiamondAxe,
            Item.DiamondBoots,
            Item.DiamondChestplate,
            Item.DiamondHelmet,
            Item.DiamondHoe,
            Item.DiamondPants,
            Item.DiamondPick,
            Item.DiamondShovel,
            Item.DiamondSword,
            Item.FishingRod,
            Item.FlintAndSteel,
            Item.GoldAxe,
            Item.GoldBoots,
            Item.GoldChestplate,
            Item.GoldHelmet,
            Item.GoldHoe,
            Item.GoldPants,
            Item.GoldPickaxe,
            Item.GoldShovel,
            Item.GoldSword,
            Item.IronAxe,
            Item.IronBoots,
            Item.IronChestplate,
            Item.IronHelmet,
            Item.IronHoe,
            Item.IronPants,
            Item.IronPick,
            Item.IronShovel,
            Item.IronSword,
            Item.LeatherBoots,
            Item.LeatherChestplate,
            Item.LeatherHelmet,
            Item.LeatherPants,
            Item.StoneAxe,
            Item.StoneHoe,
            Item.StonePick,
            Item.StoneShovel,
            Item.StoneSword,
            Item.WoodenAxe,
            Item.WoodenHoe,
            Item.WoodenPick,
            Item.WoodenShovel,
            Item.WoodenSword
        };

        public static readonly Dictionary<Item, short> ToolDuarability = new Dictionary<Item, short>() {
            // These values are just guesses. They aren't verified as correct.
            {Item.Cake, 6},
            {Item.ChainmailBoots, 132},
            {Item.ChainmailChestplate, 132},
            {Item.ChainmailHelmet, 132},
            {Item.ChainmailPants, 132},
            {Item.DiamondAxe, 1562},
            {Item.DiamondBoots, 1562},
            {Item.DiamondChestplate, 1562},
            {Item.DiamondHelmet, 1562},
            {Item.DiamondHoe, 1562},
            {Item.DiamondPants, 1562},
            {Item.DiamondPick, 1562},
            {Item.DiamondShovel, 1562},
            {Item.DiamondSword, 1562},
            {Item.FishingRod, 90},
            {Item.FlintAndSteel, 64},
            {Item.GoldAxe, 33},
            {Item.GoldBoots, 33},
            {Item.GoldChestplate, 33},
            {Item.GoldHelmet, 33},
            {Item.GoldHoe, 33},
            {Item.GoldPants, 33},
            {Item.GoldPickaxe, 33},
            {Item.GoldShovel, 33},
            {Item.GoldSword, 33},
            {Item.IronAxe, 251},
            {Item.IronBoots, 251},
            {Item.IronChestplate, 251},
            {Item.IronHelmet, 251},
            {Item.IronHoe, 251},
            {Item.IronPants, 251},
            {Item.IronPick, 251},
            {Item.IronShovel, 251},
            {Item.IronSword, 251},
            {Item.LeatherBoots, 60},
            {Item.LeatherChestplate, 60},
            {Item.LeatherHelmet, 60},
            {Item.LeatherPants, 60},
            {Item.StoneAxe, 132},
            {Item.StoneHoe, 132},
            {Item.StonePick, 132},
            {Item.StoneShovel, 132},
            {Item.StoneSword, 132},
            {Item.WoodenAxe, 60},
            {Item.WoodenHoe, 60},
            {Item.WoodenPick, 60},
            {Item.WoodenShovel, 60},
            {Item.WoodenSword, 60}
        };

        public static readonly Item[] SmeltableItems = new Item[] {
            Item.Pork,
            Item.RawFish,
            Item.Clay
        };
    }

    #endregion

    #region Blocks

    public struct Blocks
    {
        public static readonly BlockInfo[] LightEmittingBlocks = new BlockInfo[] {
            // These values are just guesses. They aren't verified as correct.
            new BlockInfo(Block.Torch, 0x0F),
            new BlockInfo(Block.RedstoneTorchOn, 0x06),
            new BlockInfo(Block.GlowingRedstoneOre, 0x06),
            new BlockInfo(Block.BurningFurnace, 0x06),
            new BlockInfo(Block.DiamondOre, 0x06),
            new BlockInfo(Block.Fire, 0x0F),
            new BlockInfo(Block.Lava, 0x0F),
            new BlockInfo(Block.MobSpawner, 0x06)
        };



        public static readonly BlockInfo[] BlockDestroyLevel = new BlockInfo[] {
            // 0 = Fists | 1 = Wood | 2 = Stone | 3 = Iron | 4 = Gold | 5 = Diamond
            new BlockInfo(Block.Adminium, 6),
            new BlockInfo(Block.Obsidian, 4),
            new BlockInfo(Block.Lava, 6),
            new BlockInfo(Block.Water, 6),
            new BlockInfo(Block.Brick, 2),
            new BlockInfo(Block.Cobblestone, 0),
            new BlockInfo(Block.DiamondBlock, 4),
            new BlockInfo(Block.Gold, 3),
            new BlockInfo(Block.Iron, 2),
            new BlockInfo(Block.Jukebox, 0),
            new BlockInfo(Block.MossyCobblestone, 0),
            new BlockInfo(Block.DoubleStair, 0),
            new BlockInfo(Block.Stair, 0),
            new BlockInfo(Block.Stone, 0),
            new BlockInfo(Block.IronDoor, 2),
            new BlockInfo(Block.MobSpawner, 3),
            new BlockInfo(Block.Dispenser, 2),
            new BlockInfo(Block.Furnace, 2),
            new BlockInfo(Block.CoalOre, 1),
            new BlockInfo(Block.DiamondOre, 4),
            new BlockInfo(Block.WoodenDoor, 1),
            new BlockInfo(Block.Fence, 1),
            new BlockInfo(Block.GoldOre, 3),
            new BlockInfo(Block.IronOre, 2),
            new BlockInfo(Block.LapisBlock, 3),
            new BlockInfo(Block.LapisOre, 3),
            new BlockInfo(Block.RedstoneOre, 3),
            new BlockInfo(Block.WoodenStairs, 1),
            //new BlockInfo(Block.Wood, 0),
            new BlockInfo(Block.Chest, 0),
            new BlockInfo(Block.Workbench, 0),
            new BlockInfo(Block.Wood, 0),
            new BlockInfo(Block.Books, 0),
            new BlockInfo(Block.LitPumpkin, 2),
            new BlockInfo(Block.Pumpkin, 2),
            new BlockInfo(Block.Signpost, 1),
            new BlockInfo(Block.NoteBlock, 1),
            new BlockInfo(Block.Sandstone, 0),
            new BlockInfo(Block.Wool, 1),
            new BlockInfo(Block.Rails, 1),
            new BlockInfo(Block.Clay, 0),
            new BlockInfo(Block.Crops, 0),
            new BlockInfo(Block.Grass, 0),
            new BlockInfo(Block.Gravel, 0),
            new BlockInfo(Block.Sponge, 0),
            new BlockInfo(Block.CakeBlock, 0),
            new BlockInfo(Block.Dirt, 0),
            new BlockInfo(Block.Ice, 2),
            new BlockInfo(Block.Lever, 2),
            new BlockInfo(Block.WoodenPressurePlate, 2),
            new BlockInfo(Block.StonePressurePlate, 2),
            new BlockInfo(Block.Sand, 2),
            new BlockInfo(Block.SoulSand, 2),
            new BlockInfo(Block.StoneButton, 2),
            new BlockInfo(Block.Cactus, 2),
            new BlockInfo(Block.Ladder, 2),
            new BlockInfo(Block.Netherrack, 2),
            new BlockInfo(Block.Glass, 1),
            new BlockInfo(Block.Glowstone , 1),
            new BlockInfo(Block.Bed, 1),
            new BlockInfo(Block.Leaves, 1),
            new BlockInfo(Block.SnowBlock, 1)
        };

        public static readonly Dictionary<Block, byte> BlastResistance = new Dictionary<Block, byte>() {
            {Block.Adminium, 255},
            {Block.Obsidian, 255},
            {Block.Lava, 255},
            {Block.Water, 255},
            {Block.Brick, 30},
            {Block.Cobblestone, 30},
            {Block.DiamondBlock, 30},
            {Block.Gold, 30},
            {Block.Iron, 30},
            {Block.Jukebox, 30},
            {Block.MossyCobblestone, 30},
            {Block.DoubleStair, 30},
            {Block.Stair, 30},
            {Block.Stone, 30},
            {Block.IronDoor, 25},
            {Block.MobSpawner, 25},
            {Block.Dispenser, 17},
            {Block.Furnace, 17},
            {Block.CoalOre, 15},
            {Block.DiamondOre, 15},
            {Block.WoodenDoor, 15},
            {Block.Fence, 15},
            {Block.GoldOre, 15},
            {Block.IronOre, 15},
            {Block.LapisBlock , 15},
            {Block.LapisOre, 15},
            {Block.RedstoneOre, 15},
            {Block.WoodenStairs, 15},
            //{Block.Wood, 15},
            {Block.Chest, 12},
            {Block.Workbench, 12},
            {Block.Wood, 10},
            {Block.Books, 7},
            {Block.LitPumpkin, 5},
            {Block.Pumpkin, 5},
            {Block.Signpost, 5},
            {Block.NoteBlock, 4},
            {Block.Sandstone, 4},
            {Block.Wool, 4},
            {Block.Rails, 3},
            {Block.Clay, 3},
            {Block.Crops, 3},
            {Block.Grass, 3},
            {Block.Gravel, 3},
            {Block.Sponge, 3},
            {Block.CakeBlock, 2},
            {Block.Dirt, 2},
            {Block.Ice, 2},
            {Block.Lever, 2},
            {Block.WoodenPressurePlate, 2},
            {Block.StonePressurePlate, 2},
            {Block.Sand, 2},
            {Block.SoulSand, 2},
            {Block.StoneButton, 2},
            {Block.Cactus, 2},
            {Block.Ladder, 2},
            {Block.Netherrack, 2},
            {Block.Glass, 1},
            {Block.Glowstone , 1},
            {Block.Bed, 1},
            {Block.Leaves, 1},
            {Block.SnowBlock, 1}
        };

        /*public static List<GlobalItem> GlobalItems = new List<GlobalItem>();

        public class GlobalItem
        {
            public short type;
            public short buyPrice;
            public short sellPrice;
            public short unitPrice;
            public Permission lowestRank;
            public List<Permission> disallow = new List<Permission>();
            public List<Permission> allow = new List<Permission>();
        }

        public static void SetGlobalItems()
        {
            GlobalItem gi = new GlobalItem();

            gi.buyPrice = 0;
            gi.sellPrice = 0;
            gi.unitPrice = 1;
            gi.lowestRank = Permission.Guest;

            foreach (Block b in Enum.GetValues(typeof(Block)))
            {
                gi.type = (short)b;
                GlobalItems.Add(gi);
            }

            foreach (Item i in Enum.GetValues(typeof(Item)))
            {
                gi.type = (short)i;
                GlobalItems.Add(gi);
            }
        }*/

        /*public static void SaveGlobalItems()
        {
            try
            {
                StreamWriter w = new StreamWriter(File.Create("properties/items.properties"));
                w.WriteLine("#   This file dictates what levels may use what items");
                w.WriteLine("#   Allowed ranks: " + Group.concatList(false, false, true));
                w.WriteLine("#   Disallow and allow can be left empty, just make sure there's 2 spaces between the colons");
                w.WriteLine("#   This works entirely on permission values, not names.");
                w.WriteLine("#   BlockName : LowestRank : Disallow : Allow");
                w.WriteLine("#   lava : 60 : 80,67 : 40,41,55");
                w.WriteLine("");

                foreach (GlobalItem bs in GlobalItems)
                {
                    if (bs.type < 255)
                    {
                        foreach (Block b in Enum.GetNames(typeof(Block)))
                        {
                            if (bs.type = b)

                        }
                    }


                    if (Block.Name(bs.type).ToLower() != "unknown")
                    {
                        string line = Block.Name(bs.type) + " : " + (int)bs.lowestRank + " : " + GrpCommands.getInts(bs.disallow) + " : " + GrpCommands.getInts(bs.allow);
                        w.WriteLine(line);
                    }
                }
                w.Flush();
                w.Close();
                w.Dispose();
            }
            catch (Exception e) { Server.ErrorLog(e); }
        }*/

        /*public static bool canPlace(Player p, short b) { return canPlace(p.info.group.permission, b); }

        public static bool canPlace(Permission givenPerm, short givenitem)
        {   
            foreach (GlobalItem g in GlobalItems)
            {
                if (givenitem == g.type)
                {
                    if ((g.lowestRank <= givenPerm && !g.disallow.Contains(givenPerm)) || g.allow.Contains(givenPerm)) return true;
                    return false;
                }
            }
            return false;
        }*/

        // These are guesses too, but are probably correct.

        public static readonly Block[] LightCarryingBlocks = new Block[] {
            Block.Air,
            Block.Water,
            Block.Lava,
            Block.StillWater,
            Block.StillLava,
            Block.RedFlower,
            Block.YellowFlower,
            Block.Sapling,
            Block.RedMushroom,
            Block.BrownMushroom,
            Block.Leaves,
            Block.Glass,
            Block.Ice,
            Block.Crops,
            Block.Lever,
            Block.RedstoneTorchOff,
            Block.RedstoneTorchOn,
            Block.RedstoneWire,
            Block.Torch,
            Block.WoodenDoor,
            Block.IronDoor,
            Block.WoodenPressurePlate,
            Block.WoodenStairs,
            Block.StonePressurePlate,
            Block.CobblestoneStairs,
            Block.StoneButton,
            Block.Reed,
            Block.Stair,
            Block.WallSign,
            Block.Signpost,
            Block.SnowBlock,
            Block.Rails,
            Block.Fence,
            Block.Ladder
        };

        public static readonly Block[] NoStackingBlocks = new Block[] {
            Block.Sapling,
            Block.Rails,
            Block.Torch,
            Block.CoalOre,
            Block.IronOre,
            Block.GoldOre,
            Block.DiamondOre,
            Block.RedstoneOre,
            Block.LapisOre
        };

        public static readonly Block[] SmeltableBlocks = new Block[] {
            Block.Sand,
            Block.Cobblestone,
            Block.MossyCobblestone,
            Block.CoalOre,
            Block.IronOre,
            Block.GoldOre,
            Block.DiamondOre,
            Block.RedstoneOre,
            Block.LapisOre
        };

        public static readonly Block[] SkyLightCarryingBlocks = new Block[] {
            Block.Air,
            Block.RedFlower,
            Block.YellowFlower,
            Block.Sapling,
            Block.RedMushroom,
            Block.BrownMushroom,
            Block.Glass,
            Block.Crops,
            Block.Lever,
            Block.RedstoneTorchOff,
            Block.RedstoneTorchOn,
            Block.Torch,
            Block.WoodenDoor,
            Block.IronDoor,
            Block.WoodenPressurePlate,
            Block.WoodenStairs,
            Block.StonePressurePlate,
            Block.CobblestoneStairs,
            Block.StoneButton,
            Block.RedstoneWire,
            Block.Reed,
            Block.Stair,
            Block.WallSign,
            Block.Signpost,
            Block.SnowBlock,
            Block.Rails,
            Block.Fence,
            Block.Ladder
        };

        public static readonly Block[] PhysicsBlocks = new Block[] {
            Block.Sand,
            Block.Water,
            Block.Lava,
            Block.Gravel,
            Block.TNT,
            Block.Stair,
            Block.Crops,
            Block.Cactus,
            Block.Reed,
            Block.Sapling,
            Block.Dirt,
            Block.Soil
        };

        public static readonly Block[] RedstoneReceptor = new Block[] {
            Block.RedstoneWire,
            Block.RedstoneTorchOff,
            Block.IronDoor,
            Block.WallSign,
            Block.Signpost,
            Block.RepeaterOff
        };

        public static readonly Block[] RedstoneActivator = new Block[] {
            Block.Lever,
            Block.RedstoneTorchOn,
            Block.WoodenPressurePlate,
            Block.StonePressurePlate,
            Block.StoneButton,
            Block.RepeaterOn
        };

        public static readonly Block[] WindowBlocks = new Block[] {
            Block.Chest,
            Block.Furnace,
            Block.BurningFurnace,
            Block.Workbench,
            Block.Dispenser
        };

        public static readonly Block[] PassThroughBlocks = new Block[] {
            Block.Air,
            Block.RedFlower,
            Block.YellowFlower,
            Block.Sapling,
            Block.RedMushroom,
            Block.BrownMushroom,
            Block.Crops,
            Block.Lever,
            Block.RedstoneTorchOff,
            Block.RedstoneTorchOn,
            Block.RedstoneWire,
            Block.Torch,
            Block.WoodenPressurePlate,            
            Block.StonePressurePlate,
            Block.StoneButton,
            Block.Reed,
            Block.WallSign,
            Block.Signpost,
            Block.Rails,
            Block.Ladder,
            Block.Portal,
            Block.SnowSurface
        };
    }

    #endregion

    #region Enums
    public enum Block : byte
    {
        Air = 0,
        Stone = 1,
        Grass = 2,
        Dirt = 3,
        Cobblestone = 4,
        Wood = 5,
        Sapling = 6,
        Adminium = 7,
        Water = 8,
        StillWater = 9,
        Lava = 10,

        StillLava = 11,
        Sand = 12,
        Gravel = 13,
        GoldOre = 14,
        IronOre = 15,
        CoalOre = 16,
        Log = 17,
        Leaves = 18,
        Sponge = 19,
        Glass = 20,

        LapisOre = 21,
        LapisBlock = 22,
        Dispenser = 23,
        Sandstone = 24,
        NoteBlock = 25,
        Bed = 26,
        /* Unused space */
        Wool = 35,
        /* Unused space */
        YellowFlower = 37,
        RedFlower = 38,
        RedMushroom = 39,
        BrownMushroom = 40,

        Gold = 41,
        Iron = 42,
        DoubleStair = 43,
        Stair = 44,
        Brick = 45,
        TNT = 46,
        Books = 47,
        MossyCobblestone = 48,
        Obsidian = 49,
        Torch = 50,

        Fire = 51,
        MobSpawner = 52,
        WoodenStairs = 53,
        Chest = 54,
        RedstoneWire = 55,
        DiamondOre = 56,
        DiamondBlock = 57,
        Workbench = 58,
        Crops = 59,
        Soil = 60,

        Furnace = 61,
        BurningFurnace = 62,
        Signpost = 63,
        WoodenDoor = 64,
        Ladder = 65,
        Rails = 66,
        CobblestoneStairs = 67,
        WallSign = 68,
        Lever = 69,
        StonePressurePlate = 70,

        IronDoor = 71,
        WoodenPressurePlate = 72,
        RedstoneOre = 73,
        GlowingRedstoneOre = 74,
        RedstoneTorchOff = 75,
        RedstoneTorchOn = 76,
        StoneButton = 77,
        SnowSurface = 78,
        Ice = 79,
        SnowBlock = 80,

        Cactus = 81,
        Clay = 82,
        Reed = 83,
        Jukebox = 84,
        Fence = 85,
        Pumpkin = 86,
        Netherrack = 87,
        SoulSand = 88,
        Glowstone = 89,
        Portal = 90,

        LitPumpkin = 91,
        CakeBlock = 92,
        RepeaterOff = 93,
        RepeaterOn = 94
    }

    public enum Item : short
    {
        IronShovel = 256,
        IronPick = 257,
        IronAxe = 258,
        FlintAndSteel = 259,
        Apple = 260,
        Bow = 261,
        Arrow = 262,
        Coal = 263,
        Diamond = 264,
        Iron = 265,

        Gold = 266,
        IronSword = 267,
        WoodenSword = 268,
        WoodenShovel = 269,
        WoodenPick = 270,
        WoodenAxe = 271,
        StoneSword = 272,
        StoneShovel = 273,
        StonePick = 274,
        StoneAxe = 275,

        DiamondSword = 276,
        DiamondShovel = 277,
        DiamondPick = 278,
        DiamondAxe = 279,
        Stick = 280,
        Bowl = 281,
        MushroomSoup = 282,
        GoldSword = 283,
        GoldShovel = 284,
        GoldPickaxe = 285,

        GoldAxe = 286,
        String = 287,
        Feather = 288,
        Gunpowder = 289,
        WoodenHoe = 290,
        StoneHoe = 291,
        IronHoe = 292,
        DiamondHoe = 293,
        GoldHoe = 294,
        Seeds = 295,

        Wheat = 296,
        Bread = 297,
        LeatherHelmet = 298,
        LeatherChestplate = 299,
        LeatherPants = 300,
        LeatherBoots = 301,
        ChainmailHelmet = 302,
        ChainmailChestplate = 303,
        ChainmailPants = 304,
        ChainmailBoots = 305,

        IronHelmet = 306,
        IronChestplate = 307,
        IronPants = 308,
        IronBoots = 309,
        DiamondHelmet = 310,
        DiamondChestplate = 311,
        DiamondPants = 312,
        DiamondBoots = 313,
        GoldHelmet = 314,
        GoldChestplate = 315,

        GoldPants = 316,
        GoldBoots = 317,
        Flint = 318,
        Pork = 319,
        GrilledPork = 320,
        Painting = 321,
        GoldenApple = 322,
        Sign = 323,
        WoodenDoor = 324,
        Bucket = 325,

        WaterBucket = 326,
        LavaBucket = 327,
        Minecart = 328,
        Saddle = 329,
        IronDoor = 330,
        RedstoneDust = 331,
        Snowball = 332,
        Boat = 333,
        Leather = 334,
        MilkBucket = 335,

        ClayBrick = 336,
        Clay = 337,
        Reed = 338,
        Paper = 339,
        Book = 340,
        Slime = 341,
        StorageMinecart = 342,
        PoweredMinecart = 343,
        Egg = 344,
        Compass = 345,

        FishingRod = 346,
        Watch = 347,
        GlowstoneDust = 348,
        RawFish = 349,
        CookedFish = 350,
        Dye = 351,
        Bone = 352,
        Sugar = 353,
        Cake = 354,
        Bed = 355,
        RedstoneRepeater = 356
    }

    public enum Record : short
    {
        Gold = 2256,
        Green = 2257
    }

    public enum Object : byte
    {
        Boat = 1,
        Minecart = 10,
        StorageCart = 11,
        PoweredCart = 12,
        ActivatedTNT = 50,
        Arrow = 60,
        ThrownSnowball = 61,
        ThrownEgg = 62,
        FallingSand = 70,
        FallingGravel = 71,
        FishingFloat = 90
    }

    public enum MobType : byte
    {
        Creeper	= 50,
        Skeleton = 51,
        Spider = 52,
        GiantZombie = 53,
        Zombie = 54,
        Slime = 55,
        Ghast = 56,
        ZombiePigman = 57,
        Pig = 90,
        Sheep = 91,
        Cow = 92,
        Hen = 93,
        Squid = 94,
        Wolf = 95
    }

    public static class Metadata
    {
        public enum Wood : byte
        {
            Normal, Redwood, Birch
        }
        public enum Slab : byte
        {
            Stone, Sandstone, Wooden, Cobblestone
        }
        public enum Liquid : byte
        {
            Full = 0x0, LavaMax = 0x3, WaterMax = 0x7, Falling = 0x8
        }
        public enum Wool : byte
        {
            White, Orange, Magenta, LightBlue, Yellow, LightGreen, Pink, Gray,
            LightGray, Cyan, Purple, Blue, Brown, DarkGreen, Red, Black
        }
        public enum Dyes : byte
        {
            InkSack, RoseRed, CactusGreen, CocoBeans, LapisLazuli, Purple, Cyan, LightGray,
            Gray, Pink, Lime, DandelionYellow, LightBlue, Magenta, Orange, BoneMeal
        }
        public enum Torch : byte
        {
            South = 0x1, North, East, West, Standing
        }
        public enum Bed : byte
        {
            West, North, East, South,
            BedFoot
        }
        public enum Tracks : byte
        {
            EastWest, NorthSouth, RiseSouth, RiseNorth, RiseEast, RiseWest,
            NECorner, SECorner, SWCorner, NWCorner
        }
        public enum Ladders : byte
        {
            East = 2, West, North, South
        }
        public enum Stairs : byte
        {
            South, North, West, East
        }
        public enum Lever : byte
        {
            SouthWall = 1, NorthWall, WestWall, EastWall, EWGround, NSGround,
            IsFlipped = 8
        }
        public enum Door : byte
        {
            Northeast, Southeast, Southwest, Northwest,
            IsOpen = 4, IsTopHalf = 8
        }
        public enum Button : byte
        {
            SouthWall = 0x1, NorthWall, WestWall, EastWall,
            IsPressed = 0x8
        }
        public enum SignPost : byte
        {
            West = 0x0,
            WestNorthwest,
            Northwest,
            NorthNorthwest,
            North,
            NorthNortheast,
            Northeast,
            EastNortheast,
            East,
            EastSoutheast,
            Southeast,
            SouthSoutheast,
            South,
            SouthSouthwest,
            Southwest,
            WestSouthwest
        }
        public enum SignWall : byte
        {
            East = 0x2, West, North, South
        }
        public enum Dispenser : byte
        {
            East = 0x2, West, North, South
        }
        public enum Furnace : byte
        {
            East = 0x2, West, North, South
        }
        public enum Pumpkin : byte
        {
            East, South, West, North
        }
        public enum RedstoneRepeater : byte
        {
            East, South, West, North,
            Tick1, Tick2, Tick3, Tick4
        }
    }
    #endregion
}
